
#include "Header.h"
#include "FilterResonance.h"
#include <math.h>
#include <vector>

struct ResonanceDataStruct
{
	int Channels;
	int Length;
	double Output;
	double Dist;
} typedef ResonanceData;


class Effect_Resonance
{
public:
	std::vector<FilterResonance> resonants;

	/// <summary>
	/// Get or set the flanger delta time.
	/// </summary>
	double GetCutoff()
	{
		return resonants[0].Cutoff;
	}
	double SetCutoff(double value)
	{
		for(auto& resonant : resonants)
		{
			resonant.Cutoff = value;
		}
	}

	/// <summary>
	/// Get or set the flanger buffer length.
	/// </summary>
	double GetRes()
	{
		return resonants[0].Res;
	}
	double SetRes(double value)
	{
		for (auto& resonant : resonants)
		{
			resonant.Res = value;
		}
	}

	Effect_Resonance()
	{
		resonants[0].Reset();
	}

	void Setup(int channels, double sampleRate)
	{
		double resonant = GetRes();
		double cutoff = GetCutoff();

		resonants.clear();
		resonants.resize(channels);
		for (int i = channels - 1; i >= 0; i--)
		{
			resonants[i].SetBitrate(sampleRate);
		}

		SetRes(resonant);
		SetCutoff(cutoff);
	}

	void Process(ResonanceData* data, double* wav_in_left, double* wav_in_right, double* wav_out_left, double* wav_out_right)
	{
		if (data->Channels == 1)
		{
			resonants[0].ProcessTime(wav_in_left, wav_out_left, data->Length);
		}
		else if (data->Channels == 2)
		{
			resonants[0].ProcessTime(wav_in_left, wav_out_left, data->Length);
			resonants[0].ProcessTime(wav_in_right, wav_out_right, data->Length);
		}
	}
};

extern "C"
{
	DECLSPEC void STDCALL Effect_Resonance_Process(ResonanceData* data,
		double* wav_in_left, double* wav_in_right, double* wav_out_left, double* wav_out_right)
	{
		double a = data->Dist > 0.98 ? 0.98 : data->Dist;
		double k = 2 * a / (1 - a);
		double output = data->Output;
		double k1 = k + 1;

		// Reference: http://www.musicdsp.org/archive.php?classid=4
		for (int c = data->Channels - 1; c >= 0; c--)
		{
			double* inputSamples = c == 0 ? wav_in_left : wav_in_right;
			double* outputSamples = c == 0 ? wav_out_left : wav_out_right;

			for (int i = data->Length - 1; i >= 0; i--)
			{
				double x = inputSamples[i];
				outputSamples[i] = (k1 * x / (1 + k * fabs(x))) * output;
			}
		}
	}
}